#include "log.h"

static log_level_t log_level = LOG_LEVEL_DEBUG;               // 日志等级默认是调试等级
static FILE *log_fp = NULL;                                   // 日志文件指针
static pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER; // 锁
// 日志等级对应的字符串
static char *log_level_strings[] = {
    "DEBUG",
    "INFO",
    "WARN",
    "ERROR",
    "FATAL"};

int log_init(const char *log_file, log_level_t level)
{

    // 日志路径检查检查
    if (log_file == NULL)
    {
        return -1;
    }
    // 日志等级检查
    if (level < LOG_LEVEL_DEBUG || level > LOG_LEVEL_FATAL)
    {
        return -1;
    }
    // 用追加模式打开日志文件
    log_fp = fopen(log_file, "a");
    // 如果日志文件打开失败就返回错误信息
    if (log_fp == NULL)
    {
        return -1;
    }
    // 设置日志等级
    log_level = level;

    return 0;
}

void log_close(void)
{
    if (log_fp != NULL)
    {
        fclose(log_fp);
        log_fp = NULL;
    }
}

void log_write(log_level_t level, const char *file, const char *func, int line, const char *fmt, ...)
{
    // 级别过滤
    if (level < log_level)
    {
        return;
    }
    // 准备向日志文件中写入日志
    // 先上锁
    pthread_mutex_lock(&log_mutex);
    // 获取当前时间并格式化
    time_t now = time(NULL);
    struct tm *tm_now = localtime(&now);
    char time_str[20];
    strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", tm_now);
    // 写入时间、日志等级、文件名、函数名、行号
    fprintf(log_fp, "[%s] [%s] [%s:%s:%d] ", time_str, log_level_strings[level], file, func, line);
    // 处理可变参数
    va_list args;
    va_start(args, fmt);
    vfprintf(log_fp, fmt, args);
    va_end(args);
    // 写入换行符并刷新文件缓冲区
    fprintf(log_fp, "\n");
    fflush(log_fp);
    // 解锁
    pthread_mutex_unlock(&log_mutex);

    return;
}